ESL Dataset
load("../data/mixture.example.RData")
intercept = 50.0
coef_x1 = 10.0
coef_x2 = -2.0
set.seed(1000)
df <- data.frame(x1 = mixture.example$x[,1],
x2 = mixture.example$x[,2]) %>%
mutate(y = intercept + coef_x1 * x1 + coef_x2 * x2 + rnorm(length(x1), 0, 5))
x.grid <- seq(min(df$x1), max(df$x1), 0.1)
y.grid <- seq(min(df$x2), max(df$x2), 0.1)
hist(df$y)

Figure (just the dataset)
xy.grid <- expand.grid(x.grid, y.grid)
names(xy.grid) <- c("x1", "x2")
p <- ggplot(df) +
geom_point(aes(x = x1, y = x2, colour = y, fill = y), pch = 21) +
geom_point(aes(x = x1, y = x2), alpha = 0.5, data = xy.grid, colour = "gray50", size = 0.02) +
theme_minimal() +
xlab("Disease Severity Score (x1)") +
ylab("Social Determinants Score (x2)") +
theme(axis.text = element_blank()) +
theme(legend.position = "bottom", panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
scale_colour_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d") +
scale_fill_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d")
print(p)
ggsave(p, filename = "../img/esl-reg-just-data.png", height=4.5, width=4, units="in", dpi=300)

Linear regression
x.grid <- seq(min(df$x1), max(df$x1), 0.05)
y.grid <- seq(min(df$x2), max(df$x2), 0.05)
xy.grid <- expand.grid(x.grid, y.grid)
names(xy.grid) <- c("x1", "x2")
m <- lm(y ~ x1 + x2, data = df)
xy.grid$yhat <- predict(m, xy.grid)
p <- ggplot(df) +
geom_point(aes(x = x1, y = x2, colour = y, fill = y), pch = 21) +
geom_point(aes(x = x1, y = x2, colour = yhat), alpha = 0.4, data = xy.grid, size = 0.5) +
theme_minimal() +
xlab("Disease Severity Score (x1)") +
ylab("Social Determinants Score (x2)") + theme(axis.text = element_blank()) +
scale_fill_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d") +
stat_contour(aes(x = x1, y = x2, z = yhat), breaks = quantile(xy.grid$yhat, seq(0, 1, 0.25)),
data = xy.grid, colour = "gray30") +
scale_colour_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d") +
theme(legend.position = "none", panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
coord_cartesian(xlim=c(min(xy.grid$x1),max(xy.grid$x1)), ylim=c(min(xy.grid$x2),max(xy.grid$x2)))
print(p)
ggsave(p, filename = "../img/esl-reg-linear.png", height=4, width=4, units="in", dpi=300)

KNN with K=15
x.grid <- seq(min(df$x1), max(df$x1), 0.05)
y.grid <- seq(min(df$x2), max(df$x2), 0.05)
xy.grid <- expand.grid(x.grid, y.grid)
names(xy.grid) <- c("x1", "x2")
m <- knn(df[,1:2], xy.grid, df[,3], k=15, prob=TRUE)
xy.grid$yhat <- as.numeric(as.character(m))
p <- ggplot(df) +
geom_point(aes(x = x1, y = x2, colour = y, fill = y), pch = 21) +
geom_point(aes(x = x1, y = x2, colour = yhat), alpha = 0.4, data = xy.grid, size = 0.5) +
theme_minimal() +
xlab("Disease Severity Score (x1)") +
ylab("Social Determinants Score (x2)") + theme(axis.text = element_blank()) +
scale_fill_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d") +
stat_contour(aes(x = x1, y = x2, z = yhat), breaks = quantile(xy.grid$yhat, seq(0, 1, 0.25)),
data = xy.grid, colour = "gray30") +
scale_colour_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d") +
theme(legend.position = "none", panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
coord_cartesian(xlim=c(min(xy.grid$x1),max(xy.grid$x1)), ylim=c(min(xy.grid$x2),max(xy.grid$x2)))
print(p)
ggsave(p, filename = "../img/esl-reg-knn-15.png", height=4, width=4, units="in", dpi=300)

Decision tree
x.grid <- seq(min(df$x1), max(df$x1), 0.05)
y.grid <- seq(min(df$x2), max(df$x2), 0.05)
xy.grid <- expand.grid(x.grid, y.grid)
names(xy.grid) <- c("x1", "x2")
m <- rpart(y ~ x1 + x2, data = df)
xy.grid$yhat <- predict(m, xy.grid)
p <- ggplot(df) +
geom_point(aes(x = x1, y = x2, colour = y, fill = y), pch = 21) +
geom_point(aes(x = x1, y = x2, colour = yhat), alpha = 0.4, data = xy.grid, size = 0.5) +
theme_minimal() +
xlab("Disease Severity Score (x1)") +
ylab("Social Determinants Score (x2)") + theme(axis.text = element_blank()) +
scale_fill_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d") +
stat_contour(aes(x = x1, y = x2, z = yhat), breaks = quantile(xy.grid$yhat, seq(0, 1, 0.25)),
data = xy.grid, colour = "gray30") +
scale_colour_gradient(name = "Recurrence\nBiomarker (y)", low = "#00bfc4", high = "#f8766d") +
theme(legend.position = "none", panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
coord_cartesian(xlim=c(min(xy.grid$x1),max(xy.grid$x1)), ylim=c(min(xy.grid$x2),max(xy.grid$x2)))
print(p)
ggsave(p, filename = "../img/esl-reg-decision-tree.png", height=4, width=4, units="in", dpi=300)

Standard deviation reduction!
set.seed(200)
df <- data.frame(y = c(rnorm(100, 0, 1), rnorm(100, 3, 1)),
gauss_id = c(rep(0.1, 100), rep(0.9, 100)),
x1 = rbinom(200, 1, 0.5)) %>%
mutate(x2 = rbinom(length(x1), 1, gauss_id)) %>%
gather(x1:x2, key = "variable", value = "value")
p <- ggplot(df) +
geom_histogram(aes(x = y, fill = as.factor(value)), position = "stack", alpha = 0.5, bins = 30) +
theme_bw() + scale_fill_discrete(name = "Variable Value") +
facet_wrap(~variable, nrow = 2) + ylab("Count") + xlab("Outcome (y)")
print(p)
ggsave(p, filename = "../img/esl-reg-decision-tree-varsplit.png", height=4, width=6, units="in", dpi=300)

LS0tCnRpdGxlOiAiUmVncmVzc2lvbiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgTGlicmFyaWVzCgpgYGB7ciBzZXR1cH0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShkcGx5cikKbGlicmFyeShzdXJ2aXZhbCkKbGlicmFyeShzdXJ2bWluZXIpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeShjbGFzcykKbGlicmFyeShycGFydCkKbGlicmFyeShycGFydC5wbG90KQpsaWJyYXJ5KHBsb3RseSkKYGBgCgojIyBFU0wgRGF0YXNldAoKYGBge3J9CmxvYWQoIi4uL2RhdGEvbWl4dHVyZS5leGFtcGxlLlJEYXRhIikKaW50ZXJjZXB0ID0gNTAuMApjb2VmX3gxID0gMTAuMApjb2VmX3gyID0gLTIuMApzZXQuc2VlZCgxMDAwKQpkZiA8LSBkYXRhLmZyYW1lKHgxID0gbWl4dHVyZS5leGFtcGxlJHhbLDFdLCAKICAgICAgICAgICAgICAgICB4MiA9IG1peHR1cmUuZXhhbXBsZSR4WywyXSkgJT4lCiAgbXV0YXRlKHkgPSBpbnRlcmNlcHQgKyBjb2VmX3gxICogeDEgKyBjb2VmX3gyICogeDIgKyBybm9ybShsZW5ndGgoeDEpLCAwLCA1KSkKeC5ncmlkIDwtIHNlcShtaW4oZGYkeDEpLCBtYXgoZGYkeDEpLCAwLjEpCnkuZ3JpZCA8LSBzZXEobWluKGRmJHgyKSwgbWF4KGRmJHgyKSwgMC4xKQpoaXN0KGRmJHkpCmBgYAoKRmlndXJlIChqdXN0IHRoZSBkYXRhc2V0KQoKYGBge3J9Cnh5LmdyaWQgPC0gZXhwYW5kLmdyaWQoeC5ncmlkLCB5LmdyaWQpCm5hbWVzKHh5LmdyaWQpIDwtIGMoIngxIiwgIngyIikKcCA8LSBnZ3Bsb3QoZGYpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgxLCB5ID0geDIsIGNvbG91ciA9IHksIGZpbGwgPSB5KSwgcGNoID0gMjEpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgxLCB5ID0geDIpLCBhbHBoYSA9IDAuNSwgZGF0YSA9IHh5LmdyaWQsIGNvbG91ciA9ICJncmF5NTAiLCBzaXplID0gMC4wMikgKyAKICB0aGVtZV9taW5pbWFsKCkgKyAKICB4bGFiKCJEaXNlYXNlIFNldmVyaXR5IFNjb3JlICh4MSkiKSArIAogIHlsYWIoIlNvY2lhbCBEZXRlcm1pbmFudHMgU2NvcmUgKHgyKSIpICsgCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudChuYW1lID0gIlJlY3VycmVuY2VcbkJpb21hcmtlciAoeSkiLCBsb3cgPSAiIzAwYmZjNCIsIGhpZ2ggPSAiI2Y4NzY2ZCIpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudChuYW1lID0gIlJlY3VycmVuY2VcbkJpb21hcmtlciAoeSkiLCBsb3cgPSAiIzAwYmZjNCIsIGhpZ2ggPSAiI2Y4NzY2ZCIpCnByaW50KHApCmdnc2F2ZShwLCBmaWxlbmFtZSA9ICIuLi9pbWcvZXNsLXJlZy1qdXN0LWRhdGEucG5nIiwgaGVpZ2h0PTQuNSwgd2lkdGg9NCwgdW5pdHM9ImluIiwgZHBpPTMwMCkKYGBgCgpMaW5lYXIgcmVncmVzc2lvbgoKYGBge3J9CnguZ3JpZCA8LSBzZXEobWluKGRmJHgxKSwgbWF4KGRmJHgxKSwgMC4wNSkKeS5ncmlkIDwtIHNlcShtaW4oZGYkeDIpLCBtYXgoZGYkeDIpLCAwLjA1KQp4eS5ncmlkIDwtIGV4cGFuZC5ncmlkKHguZ3JpZCwgeS5ncmlkKQpuYW1lcyh4eS5ncmlkKSA8LSBjKCJ4MSIsICJ4MiIpCm0gPC0gbG0oeSB+IHgxICsgeDIsIGRhdGEgPSBkZikKeHkuZ3JpZCR5aGF0IDwtIHByZWRpY3QobSwgeHkuZ3JpZCkKcCA8LSBnZ3Bsb3QoZGYpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgxLCB5ID0geDIsIGNvbG91ciA9IHksIGZpbGwgPSB5KSwgcGNoID0gMjEpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgxLCB5ID0geDIsIGNvbG91ciA9IHloYXQpLCBhbHBoYSA9IDAuNCwgZGF0YSA9IHh5LmdyaWQsIHNpemUgPSAwLjUpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgeGxhYigiRGlzZWFzZSBTZXZlcml0eSBTY29yZSAoeDEpIikgKyAKICB5bGFiKCJTb2NpYWwgRGV0ZXJtaW5hbnRzIFNjb3JlICh4MikiKSArIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50KG5hbWUgPSAiUmVjdXJyZW5jZVxuQmlvbWFya2VyICh5KSIsIGxvdyA9ICIjMDBiZmM0IiwgaGlnaCA9ICIjZjg3NjZkIikgKwogIHN0YXRfY29udG91cihhZXMoeCA9IHgxLCB5ID0geDIsIHogPSB5aGF0KSwgYnJlYWtzID0gcXVhbnRpbGUoeHkuZ3JpZCR5aGF0LCBzZXEoMCwgMSwgMC4yNSkpLCAKICAgICAgICAgICAgICAgZGF0YSA9IHh5LmdyaWQsIGNvbG91ciA9ICJncmF5MzAiKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudChuYW1lID0gIlJlY3VycmVuY2VcbkJpb21hcmtlciAoeSkiLCBsb3cgPSAiIzAwYmZjNCIsIGhpZ2ggPSAiI2Y4NzY2ZCIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSArIAogIGNvb3JkX2NhcnRlc2lhbih4bGltPWMobWluKHh5LmdyaWQkeDEpLG1heCh4eS5ncmlkJHgxKSksIHlsaW09YyhtaW4oeHkuZ3JpZCR4MiksbWF4KHh5LmdyaWQkeDIpKSkKcHJpbnQocCkKZ2dzYXZlKHAsIGZpbGVuYW1lID0gIi4uL2ltZy9lc2wtcmVnLWxpbmVhci5wbmciLCBoZWlnaHQ9NCwgd2lkdGg9NCwgdW5pdHM9ImluIiwgZHBpPTMwMCkKYGBgCgpLTk4gd2l0aCBLPTE1CgpgYGB7cn0KeC5ncmlkIDwtIHNlcShtaW4oZGYkeDEpLCBtYXgoZGYkeDEpLCAwLjA1KQp5LmdyaWQgPC0gc2VxKG1pbihkZiR4MiksIG1heChkZiR4MiksIDAuMDUpCnh5LmdyaWQgPC0gZXhwYW5kLmdyaWQoeC5ncmlkLCB5LmdyaWQpCm5hbWVzKHh5LmdyaWQpIDwtIGMoIngxIiwgIngyIikKbSA8LSBrbm4oZGZbLDE6Ml0sIHh5LmdyaWQsIGRmWywzXSwgaz0xNSwgcHJvYj1UUlVFKQp4eS5ncmlkJHloYXQgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobSkpCnAgPC0gZ2dwbG90KGRmKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSB4MSwgeSA9IHgyLCBjb2xvdXIgPSB5LCBmaWxsID0geSksIHBjaCA9IDIxKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSB4MSwgeSA9IHgyLCBjb2xvdXIgPSB5aGF0KSwgYWxwaGEgPSAwLjQsIGRhdGEgPSB4eS5ncmlkLCBzaXplID0gMC41KSArIAogIHRoZW1lX21pbmltYWwoKSArIAogIHhsYWIoIkRpc2Vhc2UgU2V2ZXJpdHkgU2NvcmUgKHgxKSIpICsgCiAgeWxhYigiU29jaWFsIERldGVybWluYW50cyBTY29yZSAoeDIpIikgKyB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudChuYW1lID0gIlJlY3VycmVuY2VcbkJpb21hcmtlciAoeSkiLCBsb3cgPSAiIzAwYmZjNCIsIGhpZ2ggPSAiI2Y4NzY2ZCIpICsKICBzdGF0X2NvbnRvdXIoYWVzKHggPSB4MSwgeSA9IHgyLCB6ID0geWhhdCksIGJyZWFrcyA9IHF1YW50aWxlKHh5LmdyaWQkeWhhdCwgc2VxKDAsIDEsIDAuMjUpKSwgCiAgICAgICAgICAgICAgIGRhdGEgPSB4eS5ncmlkLCBjb2xvdXIgPSAiZ3JheTMwIikgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobmFtZSA9ICJSZWN1cnJlbmNlXG5CaW9tYXJrZXIgKHkpIiwgbG93ID0gIiMwMGJmYzQiLCBoaWdoID0gIiNmODc2NmQiKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKG1pbih4eS5ncmlkJHgxKSxtYXgoeHkuZ3JpZCR4MSkpLCB5bGltPWMobWluKHh5LmdyaWQkeDIpLG1heCh4eS5ncmlkJHgyKSkpCnByaW50KHApCmdnc2F2ZShwLCBmaWxlbmFtZSA9ICIuLi9pbWcvZXNsLXJlZy1rbm4tMTUucG5nIiwgaGVpZ2h0PTQsIHdpZHRoPTQsIHVuaXRzPSJpbiIsIGRwaT0zMDApCmBgYAoKRGVjaXNpb24gdHJlZQoKYGBge3J9CnguZ3JpZCA8LSBzZXEobWluKGRmJHgxKSwgbWF4KGRmJHgxKSwgMC4wNSkKeS5ncmlkIDwtIHNlcShtaW4oZGYkeDIpLCBtYXgoZGYkeDIpLCAwLjA1KQp4eS5ncmlkIDwtIGV4cGFuZC5ncmlkKHguZ3JpZCwgeS5ncmlkKQpuYW1lcyh4eS5ncmlkKSA8LSBjKCJ4MSIsICJ4MiIpCm0gPC0gcnBhcnQoeSB+IHgxICsgeDIsIGRhdGEgPSBkZikKeHkuZ3JpZCR5aGF0IDwtIHByZWRpY3QobSwgeHkuZ3JpZCkKcCA8LSBnZ3Bsb3QoZGYpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgxLCB5ID0geDIsIGNvbG91ciA9IHksIGZpbGwgPSB5KSwgcGNoID0gMjEpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgxLCB5ID0geDIsIGNvbG91ciA9IHloYXQpLCBhbHBoYSA9IDAuNCwgZGF0YSA9IHh5LmdyaWQsIHNpemUgPSAwLjUpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgeGxhYigiRGlzZWFzZSBTZXZlcml0eSBTY29yZSAoeDEpIikgKyAKICB5bGFiKCJTb2NpYWwgRGV0ZXJtaW5hbnRzIFNjb3JlICh4MikiKSArIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50KG5hbWUgPSAiUmVjdXJyZW5jZVxuQmlvbWFya2VyICh5KSIsIGxvdyA9ICIjMDBiZmM0IiwgaGlnaCA9ICIjZjg3NjZkIikgKwogIHN0YXRfY29udG91cihhZXMoeCA9IHgxLCB5ID0geDIsIHogPSB5aGF0KSwgYnJlYWtzID0gcXVhbnRpbGUoeHkuZ3JpZCR5aGF0LCBzZXEoMCwgMSwgMC4yNSkpLCAKICAgICAgICAgICAgICAgZGF0YSA9IHh5LmdyaWQsIGNvbG91ciA9ICJncmF5MzAiKSArIAogIHNjYWxlX2NvbG91cl9ncmFkaWVudChuYW1lID0gIlJlY3VycmVuY2VcbkJpb21hcmtlciAoeSkiLCBsb3cgPSAiIzAwYmZjNCIsIGhpZ2ggPSAiI2Y4NzY2ZCIpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSArIAogIGNvb3JkX2NhcnRlc2lhbih4bGltPWMobWluKHh5LmdyaWQkeDEpLG1heCh4eS5ncmlkJHgxKSksIHlsaW09YyhtaW4oeHkuZ3JpZCR4MiksbWF4KHh5LmdyaWQkeDIpKSkKcHJpbnQocCkKZ2dzYXZlKHAsIGZpbGVuYW1lID0gIi4uL2ltZy9lc2wtcmVnLWRlY2lzaW9uLXRyZWUucG5nIiwgaGVpZ2h0PTQsIHdpZHRoPTQsIHVuaXRzPSJpbiIsIGRwaT0zMDApCmBgYAoKU3RhbmRhcmQgZGV2aWF0aW9uIHJlZHVjdGlvbiEKCmBgYHtyfQpzZXQuc2VlZCgyMDApCmRmIDwtIGRhdGEuZnJhbWUoeSA9IGMocm5vcm0oMTAwLCAwLCAxKSwgcm5vcm0oMTAwLCAzLCAxKSksIAogICAgICAgICAgICAgICAgIGdhdXNzX2lkID0gYyhyZXAoMC4xLCAxMDApLCByZXAoMC45LCAxMDApKSwKICAgICAgICAgICAgICAgICB4MSA9IHJiaW5vbSgyMDAsIDEsIDAuNSkpICU+JQogIG11dGF0ZSh4MiA9IHJiaW5vbShsZW5ndGgoeDEpLCAxLCBnYXVzc19pZCkpICU+JQogIGdhdGhlcih4MTp4Miwga2V5ID0gInZhcmlhYmxlIiwgdmFsdWUgPSAidmFsdWUiKQoKcCA8LSBnZ3Bsb3QoZGYpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSB5LCBmaWxsID0gYXMuZmFjdG9yKHZhbHVlKSksIHBvc2l0aW9uID0gInN0YWNrIiwgYWxwaGEgPSAwLjUsIGJpbnMgPSAzMCkgKyAKICB0aGVtZV9idygpICsgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIlZhcmlhYmxlIFZhbHVlIikgKyAKICBmYWNldF93cmFwKH52YXJpYWJsZSwgbnJvdyA9IDIpICsgeWxhYigiQ291bnQiKSArIHhsYWIoIk91dGNvbWUgKHkpIikKcHJpbnQocCkKZ2dzYXZlKHAsIGZpbGVuYW1lID0gIi4uL2ltZy9lc2wtcmVnLWRlY2lzaW9uLXRyZWUtdmFyc3BsaXQucG5nIiwgaGVpZ2h0PTQsIHdpZHRoPTYsIHVuaXRzPSJpbiIsIGRwaT0zMDApCmBgYAoKCg==